package com.joey.cloud.annotation.dic;

import cn.hutool.core.util.StrUtil;
import com.joey.cloud.communal.utils.ResponseUtil;
import com.joey.cloud.communal.vo.PageIntVo;
import com.joey.cloud.communal.vo.PageLongVo;
import com.joey.cloud.provider.service.BaseProviderService;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

/**
 * 字典注解逻辑实现
 * @author joey
 */
@Component
@Aspect
@Slf4j
public class JoeDicAspect {
    @Resource
    BaseProviderService baseProviderService;


    @Pointcut("@annotation(com.joey.cloud.annotation.dic.JoeEnableDic)"+
            "|| execution(public * com.joey.cloud..*Controller.*(..))")
    public void handle() {}

    @Around("handle()")
    public Object action(ProceedingJoinPoint joinPoint) throws Throwable {
        Object proceed = joinPoint.proceed();
        if(proceed == null){
            return null;
        }
        if(proceed instanceof ResponseUtil){
            ResponseUtil res = (ResponseUtil)proceed;
            Object data = res.getData();
            if(data == null){
                return proceed;
            }
            if(data instanceof PageLongVo){
                PageLongVo page = (PageLongVo)data;
                List list = page.getList();
                List jsonList = buildList(list);
                page.setList(jsonList);
                res.setData(page);
                return res;
            }
            if(data instanceof PageIntVo){
                PageIntVo page = (PageIntVo)data;
                List list = page.getList();
                List jsonList = buildList(list);
                page.setList(jsonList);
                res.setData(page);
                return res;
            }
            if(data instanceof List || data instanceof ArrayList){
                List list = (List)data;
                List jsonList = buildList(list);
                res.setData(jsonList);
                return res;
            }
            JoeEnableDic annotation = data.getClass().getAnnotation(JoeEnableDic.class);
            if(annotation==null){
                return proceed;
            }
            res.setData(buildItem(data));
            return res;
        }
        if(proceed instanceof List || proceed instanceof ArrayList){
            return buildList(proceed);
        }
        JoeEnableDic annotation = proceed.getClass().getAnnotation(JoeEnableDic.class);
        if(annotation==null){
            return proceed;
        }
        return buildItem(proceed);
    }

    /**
     * 翻译列表
     * @param proceed
     * @return
     * @throws IllegalAccessException
     */
    private List buildList(Object proceed) throws Exception {
        List list = (List)proceed;
        if(list==null||list.size()==0){
            return list;
        }
        JoeEnableDic annotation = list.get(0).getClass().getAnnotation(JoeEnableDic.class);
        if(annotation == null){
            return list;
        }
        List jsonList = new ArrayList<>();
        for(Object item : list){
            jsonList.add(buildItem(item));
        }
        return jsonList;
    }

    /**
     * 翻译对象
     * @param item
     * @return
     * @throws IllegalAccessException
     */
    private Object buildItem(Object item) throws Exception {
        Field[] fields = item.getClass().getDeclaredFields();
        if(fields!=null && fields.length>1){
            for(Field field:fields){
                field.setAccessible(true);
                JoeDicField annotation = field.getAnnotation(JoeDicField.class);
                if (annotation != null && StrUtil.isNotEmpty(annotation.field())) {
                    Field valueField = item.getClass().getDeclaredField(annotation.field());
                    if(valueField!=null){
                        valueField.setAccessible(true);
                        Object value = valueField.get(item);
                        if(value!=null){
                            String text = baseProviderService.queryDicText(annotation.type(),annotation.key(),value);
                            field.set(item,text);
                        }
                    }
                }
            }
        }
        return item;
    }

}
